package cn.mafangui.hotel.advice;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Base64;

/**
 * web 入出参日志切面
 *
 * @author LIJIAREN515
 * @date 2022-5-18
 */
@Aspect
@Component
@Slf4j
@Order(100)
public class WebLogAspect {
    private final ObjectMapper objectMapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    @Value("${sp.apollo.isStg:false}")
    private boolean isStg;

    @Pointcut("@annotation(com.ph.sp.progress.web.advice.WebLog)")
    public void webLog(){
        //无需实现
    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        try {
            Object[] args = proceedingJoinPoint.getArgs();
            log.info("URL: [{}], RequestArgs [{}]", getRequestUrl(), new Gson().toJson(args));
        } catch (Exception e){
            log.warn("webLog before 日志异常", e);
        }

        Object result = proceedingJoinPoint.proceed();
        try{
            byte[] responseBytes = objectMapper.writeValueAsBytes(result);
            log.info("ResponseArgs {}", isStg ? result:Base64.getEncoder().encodeToString(responseBytes));
        }catch (Exception e){
            log.warn("webLog after 日志异常", e);
        }

        return result;
    }

    private String getRequestUrl(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if(requestAttributes == null){
            return "";
        }
        HttpServletRequest request = requestAttributes.getRequest();
        return request.getRequestURL().toString();
    }

    public String getAspectLogDescription(JoinPoint joinPoint) throws ClassNotFoundException {
//        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for(Method method : methods){
            if(method.getName().equals(methodName)){
                Class<?>[] clazzs = method.getParameterTypes();
                if(clazzs.length == arguments.length){
                    description.append(method.getAnnotation(WebLog.class).description());
                    break;
                }
            }
        }
        return description.toString();
    }

}
